package controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import pluginFactory.PluginsCharger;
import pluginInterfaces.IRecommender;
import utils.JFileChooserClass;
import utils.output.OutputJarFile;
import viewInterfaces.AbstractViewFactory;
import viewInterfaces.IViewOutputJarSetup;
import controllerInterfaces.IControllerBenchmarkPanel;
import controllerInterfaces.IControllerCLI;
import controllerInterfaces.IControllerOutputJarSetup;

/**
 * Controller class that sets the parameters of the component output jar.
 * 
 * @author Andy Cullache
 */
public class ControllerOutputJarSetup implements IControllerOutputJarSetup{
	
	private IControllerBenchmarkPanel controllerBenckmarkPanel;
	private IControllerCLI controllerCLI;
	private IViewOutputJarSetup view;
	
	/**
	 * Default constructor.
	 */
	public ControllerOutputJarSetup(){
		createView();
	}
	
	/**
	 * 
	 * @param controllerWithView If true then this it creates view for controller, otherwise, not
	 */
	public ControllerOutputJarSetup(boolean controllerWithView){
		if(controllerWithView)
		{
			createView();
		}			
	}
	
	private void createView()
	{
		view = AbstractViewFactory.getAbstractViewFactory().getOutputSetupView();
		view.setController(this);
	}
	
	/**
	* Sets the benchmark panel controller as controller of this class.
	* 
	* @param controller      panel controller class benchmark.
	*/
	public void setController(IControllerBenchmarkPanel controller){
		this.controllerBenckmarkPanel = controller;
	}
	
	
	/**
	* Sets the CLI controller as controller of this class.
	* 
	* @param controller      CLI controller class
	*/
	public void setController(IControllerCLI controller){
		this.controllerCLI = controller;
	}
	
	
	/**
	* Opens a view to set the directory and name of the component jar.
	* 
	* @return      a set of "String" size 2, contains the name and path of the component to generate.
	*/
	public String[] selectDirectory(){
		return JFileChooserClass.selectFileDirectoryToSave("RBox output",".jar","Save Jar: Select directory");
	}

	/**
	* Returns the list of configurations of algorithms present in the current project.
	* 
	* @return      configuration list of algorithms.
	*/
	@Override
	public List<IRecommender> getRecommenderList() {
		return controllerBenckmarkPanel.getRecommenderList();
	}

	/**
	* Creates the output component as a jar file.
	* 
 	* @param nameSave      jar file name.
 	* @param controller      jar file directory.
 	* @param controller      configuration algorithm that is included in the jar file.
	*/
	@Override
	public void createJarOutput(String nameSave, String dirPath, IRecommender recom) {
		String directoryAlgorithm = getDirectoryAlgorithm(recom);
		File dir = new File("Temp//config");
		if ( !dir.exists() )  
            dir.mkdirs(); 
		File alg = new File("Temp//config//AlgorithmConfig");
		try {
				ObjectOutputStream oo = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(alg)));
				oo.writeObject(recom.getAlgorithm());
				oo.close();
				
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			} catch (IOException e1) {
				e1.printStackTrace();
			}	
		try {
			new OutputJarFile().generateJarOutput(nameSave, dirPath, directoryAlgorithm);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	* Returns the directory of "algorithm" that is related to the configuration algorithm that comes as a parameter. 
	* Deliver the plugin path recommendation algorithmCreates the output component as a jar file.
	* 
 	* @param recom      configuration algorithm.
 	* @return controller      algorithm PATH of plugin.
	*/
	private String getDirectoryAlgorithm(IRecommender recom){
		String algotihmName = recom.getAlgorithm().getClass().getCanonicalName();
		File[] jars = PluginsCharger.Finder("plugins//recommender");
		algotihmName = (algotihmName.replace(".", "/") +".class");
    	try {
    		for(File jar : jars){
				JarInputStream jarInput = new JarInputStream(new FileInputStream(jar));
				JarEntry jarEntry=null;
		    	
		    	while((jarEntry=jarInput.getNextJarEntry())!=null){
		    		String entryName = jarEntry.getName();
		    		
		    		if(algotihmName.equals(entryName))
		    		{
		    			return jar.getPath();
		    		}
		    	}
    		}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		return null;
	}
}
